import UIKit

/**
    B站：https://www.bilibili.com/video/BV144411C7Gg?p=29
    B站：https://www.bilibili.com/video/BV144411C7Gg?p=30

    第29课
        1. 类的继承
        2. 向下类型转换
 */


class Person {
    var name: String = ""
    var age: Int = 0
    var height: Double = 0.0
    
    init(name: String, age: Int, height: Double) {
        self.name = name
        self.age = age
        self.height = height
    }
    
    func getName() -> String {
        return self.name
    }
}

class Student: Person {
    var className: String = ""
    var grade: Int = 0
    
    // 构造器/初始化器 - 1
    init(name: String, age: Int, height: Double, className: String, grade: Int) {
        // 注意这里 super.init
        super.init(name: name, age: age, height: height)
        self.className = className
        self.grade = grade
    }
    
    // 构造器/初始化器 - 2
//    // convenience [kənˈviːniəns]  n. 方便;适宜;便利
//    convenience init(name: String, age: Int, height: Double, className: String, grade: Int) {
          // 注意这里 self.init
//        self.init(name: name, age: age, height: height)
//        self.className = className
//        self.grade = grade
//    }
}

let xiaoming = Student(name: "小明", age: 11, height: 1.77, className: "1班", grade: 1)
print("学生-小明=>", xiaoming.name, xiaoming.age, xiaoming.height, xiaoming.className, xiaoming.grade)
print("学生-小明=>", xiaoming)
print("学生-小明=> \(xiaoming)")
print(xiaoming.getName())

print("学生-小明  type-of=>", type(of: xiaoming))

// --------------------------------------------------------------

//（多态）封装-继承-多态
let xiaoli:Person = Student(name: "小李", age: 11, height: 1.77, className: "1班", grade: 1)
print("学生-小李=>", xiaoli)
print("学生-小李=> \(xiaoli)")
print(xiaoli.getName())

print("学生-小李 type-of=>", type(of: xiaoli))

// --------------------------------------------------------------
print("\n 向下类型转换 \n")
// --------------------------------------------------------------

// 向下类型转换

// 定义
let xiaowang:Any = Student(name: "小王", age: 11, height: 1.77, className: "1班", grade: 1)
print("学生-小王 type-of=>", type(of: xiaowang))

// error: 因为 Any 没有 getName() 方法
// print(xiaowang.getName())

// 1 使用 ?、？？ 向下转换 (忘记了 看第2课)
print("1-0 xiaowang is Student =>", xiaowang is Student)
let s = xiaowang as? Student
print("1-1 s?.getName()=", s?.getName() ?? "unknow")

// guard 向下转换
func testXW() -> Student {
    let xw = xiaowang as? Student
    guard xw != nil else {
        print("2-0 假")
// ***************** 【注意】【注意】【注意】【注意】【注意】【注意】 ************************
        // 构造器/初始化器 - 1， 下面初始化，就只能用 student里面用的init
        return Student(name: "unkonw", age: 0, height: 0, className: "0班", grade: 0)
        
        // 【 error 】: Missing arguments for parameters 'className', 'grade' in call
//        return Student(name: "unkonw", age: 0, height: 0)
        
//        构造器/初始化器 - 2, 下面2个初始化都行
//        return Student(name: "unkonw", age: 0, height: 0, className: "0班", grade: 0)
//        return Student(name: "unkonw", age: 0, height: 0)
    }
    print("2-1 真")
    return xw!
}
let xw: Student = testXW()
print("2-2 xw.getName()=", xw.getName())


// 3 使用 !(强制转换) 向下转换
print("3-0 强制转换=", (xiaowang as! Student).getName())
